unit cx_CBR.ru;


interface

uses
  //msxmldom,
  //XMLIntf,
  //XMLDoc,
  SysUtils,
  //ActiveX,
  cx_vars,
  DateUtils,
  //StrUtils,
  m_api,
  m_globaldefs,
  cx_http,
  cx_XML;

function CBRru_GetRate(CurrencyTo: String): TRates;

implementation

uses
  Windows,
  cx_procs;

const
  cx_cbrru_host = 'http://www.cbr.ru';
  cx_cbrru_port = 80;

  //xml tags
  cx_ValCurs = 'ValCurs';
  cx_Record = 'Record';
  cx_Date = 'Date';
  cx_Nominal = 'Nominal';
  cx_Value = 'Value';

function TransformCurrency(Currency:string) : string;
begin

if currency='AUD' then result:= 'R01010';
if currency='GBP' then result:= 'R01035';
if currency='BYR' then result:= 'R01090';
if currency='DKK' then result:= 'R01215';
if currency='USD' then result:= 'R01235';
if currency='EUR' then result:= 'R01239';
if currency='ISK' then result:= 'R01310';
if currency='KZT' then result:= 'R01335';
if currency='CAD' then result:= 'R01350';
if currency='NOK' then result:= 'R01535';
if currency='XDR' then result:= 'R01589';
if currency='SGD' then result:= 'R01625';
if currency='TRL' then result:= 'R01700';
if currency='UAH' then result:= 'R01720';
if currency='SEK' then result:= 'R01770';
if currency='CHF' then result:= 'R01775';
if currency='JPY' then result:= 'R01820';
if currency='AZM' then result:= 'R01020';
if currency='ALL' then result:= 'R01025';
if currency='SCR' then result:= 'R01595';
if currency='SYP' then result:= 'R01630';
if currency='SKK' then result:= 'R01635';
if currency='SIT' then result:= 'R01640';
if currency='SOS' then result:= 'R01650';
if currency='SDG' then result:= 'R01660';
if currency='SRG' then result:= 'R01665';
if currency='TJS' then result:= 'R01670';
if currency='THB' then result:= 'R01675';
if currency='TWD' then result:= 'R01680';
if currency='BDT' then result:= 'R01685';
if currency='TZS' then result:= 'R01690';
if currency='TND' then result:= 'R01695';
if currency='TMM' then result:= 'R01710';
if currency='UGX' then result:= 'R01714';
if currency='UZS' then result:= 'R01717';
if currency='UYU' then result:= 'R01725';
if currency='PHP' then result:= 'R01743';
if currency='DJF' then result:= 'R01746';
if currency='XAF' then result:= 'R01748';
if currency='HRK' then result:= 'R01755';
if currency='CZK' then result:= 'R01760';
if currency='CLP' then result:= 'R01765';
if currency='LKR' then result:= 'R01780';
if currency='NULL' then result:= 'R01785';
if currency='EEK' then result:= 'R01795';
if currency='ETB' then result:= 'R01800';
if currency='YUN' then result:= 'R01805';
if currency='ZAR' then result:= 'R01810';
if currency='KRW' then result:= 'R01815';
if currency='DZD' then result:= 'R01030';
if currency='AOA' then result:= 'R01040E';
if currency='ARS' then result:= 'R01055';
if currency='AMD' then result:= 'R01060';
if currency='AFN' then result:= 'R01065';
if currency='BHD' then result:= 'R01080';
if currency='BGN' then result:= 'R01100';
if currency='BOB' then result:= 'R01105';
if currency='BWP' then result:= 'R01110';
if currency='BND' then result:= 'R01111';
if currency='BRL' then result:= 'R01115';
if currency='BIF' then result:= 'R01120';
if currency='HUF' then result:= 'R01135';
if currency='VEF' then result:= 'R01140';
if currency='KPW' then result:= 'R01145';
if currency='VND' then result:= 'R01150';
if currency='GMD' then result:= 'R01160';
if currency='GHS' then result:= 'R01165';
if currency='GNF' then result:= 'R01175';
if currency='HKD' then result:= 'R01200';
if currency='GEL' then result:= 'R01210';
if currency='AED' then result:= 'R01230';
if currency='ZWD' then result:= 'R01233';
if currency='EGP' then result:= 'R01240';
if currency='ZMK' then result:= 'R01250';
if currency='ILS' then result:= 'R01265';
if currency='INR' then result:= 'R01270';
if currency='IDR' then result:= 'R01280';
if currency='JOD' then result:= 'R01285';
if currency='IQD' then result:= 'R01290';
if currency='IRR' then result:= 'R01300';
if currency='YER' then result:= 'R01330';
if currency='QAR' then result:= 'R01355';
if currency='KES' then result:= 'R01360';
if currency='CYP' then result:= 'R01365';
if currency='KGS' then result:= 'R01370';
if currency='CNY' then result:= 'R01375';
if currency='COP' then result:= 'R01380';
if currency='CDF' then result:= 'R01383';
if currency='CRC' then result:= 'R01385';
if currency='KWD' then result:= 'R01390';
if currency='CUP' then result:= 'R01395';
if currency='LAK' then result:= 'R01400';
if currency='LVL' then result:= 'R01405';
if currency='SLL' then result:= 'R01410';
if currency='LBP' then result:= 'R01420';
if currency='LYD' then result:= 'R01425';
if currency='SZL' then result:= 'R01430';
if currency='LTL' then result:= 'R01435';
if currency='MUR' then result:= 'R01445';
if currency='MRO' then result:= 'R01450';
if currency='MKD' then result:= 'R01460';
if currency='MWK' then result:= 'R01465';
if currency='MGF' then result:= 'R01470';
if currency='MYR' then result:= 'R01475';
if currency='MTL' then result:= 'R01480';
if currency='MAD' then result:= 'R01485';
if currency='MXN' then result:= 'R01495';
if currency='MZM' then result:= 'R01498';
if currency='MDL' then result:= 'R01500';
if currency='MNT' then result:= 'R01503';
if currency='NPR' then result:= 'R01515';
if currency='NGN' then result:= 'R01520';
if currency='NIO' then result:= 'R01525';
if currency='NZD' then result:= 'R01530';
if currency='OMR' then result:= 'R01540';
if currency='PKR' then result:= 'R01545';
if currency='PYG' then result:= 'R01555';
if currency='PEN' then result:= 'R01560';
if currency='PLN' then result:= 'R01565';
if currency='KHR' then result:= 'R01575';
if currency='SAR' then result:= 'R01580';
if currency='ROL' then result:= 'R01585';

end;

function CBRru_GetRate(CurrencyTo: String): TRates;
var
    //XML : IXMLDocument;
    i, nc, qty{, NumRates} : Integer;
    value, rate : Real;
    RateDate : TDateTime;
    //{msg,} tmr, tdy, rdt : string;
    response: WideString;
    //DateFormat : TFormatSettings;
    //
    root, actnode, datanode: HXML;
    //tmp: PAnsiChar;
    tmp: PWideChar;
begin
  result.success:=false;
  //
  result.coming.rate:=0;
  result.coming.date:=cx_Tomorrow;
  result.current.rate:=0;
  result.current.date:=cx_Today;
  result.previous.rate:=0;
  result.previous.date:=cx_DateFrom;

//         showmessage(cx_DateFromStr+' '+cx_TomorrowStr);
        response:=HTTP_NL_Get(cx_cbrru_host+'/scripts/XML_dynamic.asp?date_req1='+cx_DateFromStr+'&date_req2='+cx_TomorrowStr+'&VAL_NM_RQ='+TransformCurrency(currencyTo));
        //showmessage('['+response+']'); //debug
        if response='' then //no response - may be network failure
          Exit;
        //CoInitialize(nil);
        {
        xml:=NewXMLDocument;
        xml.XML.Clear;
        xml.XML.Text:=Response;
        //showmessage(xml.XML.Text);
        XML.Active:=True;
        DecimalSeparator:=',';
        if XML.ChildNodes['ValCurs'].ChildNodes.Count<3 then exit;
       For i:=XML.ChildNodes['ValCurs'].ChildNodes.Count-3 to XML.ChildNodes['ValCurs'].ChildNodes.Count-1 do
        begin;
          RateDate:=DateTimeStrEval('dd.mm.yyyy',XML.ChildNodes['ValCurs'].ChildNodes[i].Attributes['Date']);
          qty :=StrToInt(XML.ChildNodes['ValCurs'].ChildNodes[i].ChildNodes['Nominal'].NodeValue);
          value:=StrToFloat(XML.ChildNodes['ValCurs'].ChildNodes[i].ChildNodes['Value'].NodeValue);
          rate:=value/qty;

          rdt:=datetostr(RateDate);
          tmr:=datetostr(cx_Tomorrow);
          tdy:=datetostr(cx_today);

          if CompareDateTime(RateDate,cx_Today)=0 then
            begin
              result.current.rate:=rate;
              result.current.date:=RateDate;
            end;

          if CompareDateTime(RateDate,cx_Today)>0 then
            begin
              result.coming.rate:=rate;
              result.coming.date:=RateDate;
            end;

          if CompareDateTime(RateDate,cx_Today)<0 then
            if result.previous.date<RateDate then
              begin
                result.previous.rate:=rate;
                result.previous.date:=RateDate;
              end;



        end;
 //           showmessage(currencyto+chr(13)+chr(10)+floattostr(result.previous.rate)+chr(13)+chr(10)+
 //             floattostr(result.current.rate)+chr(13)+chr(10)+
  //            floattostr(result.coming.rate)+chr(13)+chr(10));

        if result.current.rate=0  then
         if result.previous.rate<>0 then
          begin
            result.current.rate:=result.previous.rate;
   //         showmessage('No Current Rate!');
          end;

        result.success:=true;
        }
        //
        with cx_XMLw do
         begin
          {
          try
          FillChar(tmp, 1024, 0);
          except
           ShowMessage('Memory allocation error');
          end;
          try
          StrPCopy(tmp, response);
          ShowMessage(tmp^);
          except
           ShowMessage('String copy error');
          end;
          }
          {
          try
          mGetMem(tmp, 4096);
          StrDupW(tmp, PWideChar(response));
          ShowMessage(tmp);
          except
           MessageBox(0, 'String convert error', piShortName, MB_OK or MB_ICONERROR);
          end;
          mFreeMem(tmp);
          }
          try
           root:=parseString(PWideChar(response), @i, cx_ValCurs);
           //root:=parseString(tmp, @i, cx_ValCurs);
          except
           MessageBox(0, 'Parse error', piShortName, MB_OK or MB_ICONERROR);
           root:=0;
          end;
          if root<>0 then
           begin
            //ShowMessage(toString(root, @i)); //debug
            DecimalSeparator:=',';
            nc:=getChildCount(root);
            if nc<3 then exit;
            For i:=nc-3 to nc-1 do
             begin;
              //actnode:=getNthChild(root, cx_ValCurs, i);
              actnode:=getNthChild(root, cx_Record, i);
              if actnode=0 then
                Continue;
              //ShowMessage(toString(actnode, @qty)); //debug
              tmp:=getAttrValue(actnode, cx_Date);
              if tmp<> nil then
               begin
                //ShowMessage(tmp); //debug
                RateDate:=DateTimeStrEval('dd.mm.yyyy', tmp);
               end
              else
                RateDate:=Date;
              //
              //datanode:=getChildByAttrValue(actnode, cx_Nominal, nil, nil);
              datanode:=getNthChild(actnode, cx_Nominal, 0);
              if datanode=0 then
                qty:=0
              else
               begin
                tmp:=getText(datanode);
                if tmp=nil then
                  qty:=0
                else
                 begin
                  //ShowMessage(tmp); //debug
                  qty :=StrToInt(tmp);
                 end;
               end;
              //
              //datanode:=getChildByAttrValue(actnode, cx_Value, nil, nil);
              datanode:=getNthChild(actnode, cx_Value, 0);
              if datanode=0 then
                value:=0
              else
               begin
                tmp:=getText(datanode);
                if tmp=nil then
                  value:=0
                else
                 begin
                  //ShowMessage(tmp); //debug
                  value:=StrToFloat(tmp);
                 end;
               end;
              if qty<>0 then
                rate:=value/qty
              else
                rate:=0;
              {
              rdt:=datetostr(RateDate);
              tmr:=datetostr(cx_Tomorrow);
              tdy:=datetostr(cx_today);
              }
              if CompareDateTime(RateDate,cx_Today)=0 then
               begin
                result.current.rate:=rate;
                result.current.date:=RateDate;
               end;

              if CompareDateTime(RateDate,cx_Today)>0 then
               begin
                result.coming.rate:=rate;
                result.coming.date:=RateDate;
               end;

              if CompareDateTime(RateDate,cx_Today)<0 then
               if result.previous.date<RateDate then
                begin
                 result.previous.rate:=rate;
                 result.previous.date:=RateDate;
                end;
             end;
            destroyNode(root);
            //
            if result.current.rate=0  then
             begin
              if result.previous.rate<>0 then
                result.current.rate:=result.previous.rate;
             end;
            result.success:=true;
           end
          else
           begin
            //not parced
            //MessageBox(0, 'Zero root!', piShortName, MB_OK or MB_ICONEXCLAMATION);
           end;
         end;
        //
        //CoUninitialize;
end;

end.
